<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.0 / SVN信息: $Id: class.JCAT_ViewHtml.php 1603 2009-03-31 15:35:42Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/
namespace JCAT ;

include_once __DIR__.'/../ViewAndUICtrl/class.JCAT_View.php';
include_once __DIR__.'/interface.JCAT_IViewHtml.php';
include_once __DIR__.'/interface.JCAT_IJSObject.php';
include_once __DIR__.'/HTMLResource/interface.JCAT_IHTMLResourceContainer.php';

/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
class ViewHtml extends View
		implements IViewHtml, IJSObject, IHTMLResourceContainer
{

	/**
	 * 
	 * @access	public
	 * @param	$sName			string					视图名称
	 * @param	$aParent		IViewContainer	父视图 或 控制器
	 * @param	$sTemplate		string					模板文件名称
	 * @param	$aUI=null		IUIHtml			UI 对象
	 * @return	void
	 */
	public function ViewHtml( $sName, IViewContainer $aParent, $sTemplate, IUIHtml $aUI=null )
	{
		ASSERT::ASSERT_STRING($sTemplate) ;
		
		// 创建/设置 UI对象
		$this->SetUI($aUI?$aUI:self::CreateShareUI()) ;
		
		$this->SetTemplate($sTemplate) ;
		
		// 父类构造函数
		$this->View($sName,$aParent) ;
	}
	
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sTemplate		string					模板文件名称
	 * @static
	 * @return	void
	 */
	static public function CreateView($sTemplate)
	{
		return new self('View:'.++self::$nViewGlabalIdx,new DoNothing(),$sTemplate) ;
	}

	/**
	 * 取得 JS UI控件对象的变量名
	 *
	 * @access	public
	 * @param	
	 * @return	void
	 */
	public function GetJSVariableName()
	{
		return 'theView' . $this->GetName() ;
	}
	
	/**
	 * 为所有 UIHtml 维护一个共享的 UIHtml 全局实例
	 *
	 * @access	public
	 * @return	UIHtml
	 */
	static public function CreateShareUI()
	{
		if( !self::$aShareGlobalUI )
		{
			self::$aShareGlobalUI = new UIHtml() ;
			
			// 设置 View Node 编译器
			$aParserManager = self::$aShareGlobalUI->GetParserManager() ;
			ASSERT::ASSERT_INSTANCE($aParserManager,'JCAT\IUIObjectProcessorManager') ;
			
			$theHtmlNodeParser = $aParserManager->GetProcessor('UI.Html.Node') ;
			ASSERT::ASSERT_INSTANCE($theHtmlNodeParser,'JCAT\UIHtmlNodeParser') ;
			
			$theCompilerManager = $theHtmlNodeParser->GetCompilerManager() ;
			ASSERT::ASSERT_INSTANCE($theCompilerManager,'JCAT\IUIObjectProcessorManager') ;
			
			$theCompilerManager->AddAutoloadProcessorDir( dirname(__FILE__).'/NodeCompiler/' ) ;
		}
		
		return self::$aShareGlobalUI ;
	}
	

	/**
	 * set the ui template filename 
	 * 
	 * @access	public
	 * @param 	$sTemplate		string   the template filename
	 * @return	void
	 */
	public function SetTemplate($sTemplate) 
	{
		$this->sTemplate = $sTemplate ;
	}
	
	/**
	 * get the ui template filename 
	 * 
	 * @access	public
	 * @return	string
	 */
	public function GetTemplate() 
	{
		return $this->sTemplate ;
	}



	/**
	 * 显示视图
	 * 
	 * @access	public
	 * @param	$bDisplayAtOnce=true			bool
	 * @return	void
	 */
	public function ShowView($bDisplayAtOnce=true) 
	{
		if(!$this->bEnableView)
		{
			return ;
		}
		
		$aUI = $this->GetUI() ;
		ASSERT::ASSERT_INSTANCE($aUI,'JCAT\UIHtml') ;
		
		// 创建 模版变量备忘录
		$aOldVars = $aUI->CreateVarSetMemento() ;
		
		// 设置模版变量
		$aController = $this->GetParentController() ;
		$aModel = $this->GetModel() ;
		$aUI->SetVar('TheView',$this) ;
		$aUI->SetVar('TheController',$aController) ;
		$aUI->SetVar('TheModel',$aModel) ;
		$aUI->SetVar('TheRequest',$aController->GetRequest()) ;
		
		// 显示视图
		$sReturn = $aUI->Display($this->sTemplate,$bDisplayAtOnce?(UIHtml::DONT_RETURN|UIHtml::OUTPUT_ATONCE):0) ;
		
		// 初始化视图
		// $this->InitializeJS() ;
		
		// 恢复模版变量
		$aUI->SetVarSetMemento($aOldVars) ;
		
		return $sReturn ;
	}
	
	
	/**
	 * 启用/禁用 视图
	 * 
	 * @access	public
	 * @param	$bEnableView	bool			what's this
	 * @return	old_value
	 */
	public function EnableView($bEnableView=true)
	{
		$old_value = $this->bEnableView ;
		$this->bEnableView = $bEnableView? true: false ;
		return $old_value ;
	}
	
	
	/**
	 * 初始化JS 视图对象
	 *
	 * @access	public
	 * @return	void
	 */
	public function InitializeViewForHtml()
	{		
		print "<script>\r\n" ;
		
		// 创建JS视图对象
		$this->InitializeJS_ConstructView() ;
		
		// 加入 UICtrl
		$this->InitializeJS_AddUICtrl() ;
		
		// 添加到 父视图
		$this->InitializeJS_AddToParentView() ;
		
		// 加入 子视图
		$this->InitializeJS_AddChildrenView() ;
		
		print "</script>" ;
	}
	
	/**
	 * 设置视图变量
	 *
	 * @access	public
	 * @param	$NameOrVars		array,string		变量名称 或 包含所有变量的数组
	 * @param	$Value				mixed			变量值
	 * @return	old_value
	 */
	public function SetViewVar( $NameOrVars, $Value=null )
	{
		$aUI = $this->GetUI() ;
		return $aUI->SetVar($NameOrVars,$Value) ;
	}
	
	/**
	 * 产生 创建JS视图对象 的JS代码
	 *
	 * @access	protected
	 * @return	string
	 */
	protected function InitializeJS_ConstructView()
	{
		$sViewName = $this->GetName() ;
		$sViewVaribleName = $this->GetJSVariableName() ;
		
		print "var {$sViewVaribleName} = new JCAT.MVC.View('{$sViewName}') ;\r\n" ;
	}
	
	/**
	 * 产生 JS视图对象 加入 UICtrl 的JS代码
	 *
	 * @access	protected
	 * @return	string
	 */
	protected function InitializeJS_AddUICtrl()
	{
		if( $this->GetUICtrlCount() )
		{
			$sViewVaribleName = $this->GetJSVariableName() ;
				
			print "\r\n// 加入 UICtrl\r\n" ;
			$aIterator = $this->CreateUICtrlIterator() ;
			$aIterator->First() ;
			while( !$aIterator->IsDone() )
			{
				$aUICtrl = $aIterator->Current() ;
				ASSERT::ASSERT_INSTANCE($aUICtrl,'JCAT\IJSObject')  ;
				$sUICtrlJSVarName = $aUICtrl->GetJSVariableName() ;
				
				print "{$sViewVaribleName}.AddUICtrl({$sUICtrlJSVarName});\r\n" ;
				
				$aIterator->Next() ;
			}
		}
	}

	
	/**
	 * 产生 加入到父视图 UICtrl 的JS代码
	 *
	 * @access	protected
	 * @return	string
	 */
	protected function InitializeJS_AddToParentView()
	{
		$aParent = $this->GetParent() ;
		if( $aParent and GlobalFunc::IsKindOf($aParent,'IView') )
		{
			ASSERT::ASSERT_INSTANCE($aParent,'JCAT\IJSObject')  ;
			$sParentVarName = $aParent->GetJSVariableName() ;
			$sViewVaribleName = $this->GetJSVariableName() ;
				
			print "\r\n// 如果父视图已经优先创建, 加入到父视图中\r\n" ;
			print "if( typeof({$sParentVarName})=='object' ){\r\n" ;
			print "	{$sParentVarName}.AddView({$sViewVaribleName}) ;\r\n"  ;
			print "}\r\n" ;
		}
	}
	
	/**
	 * 产生 加入子视图 UICtrl 的JS代码
	 *
	 * @access	protected
	 * @return	string
	 */
	protected function InitializeJS_AddChildrenView()
	{
		if( $this->GetViewCount() )
		{
			print "\r\n// 如果子视图已经优先创建, 加入子视图\r\n" ;
			$aIterator = $this->CreateViewIterator() ;
			$aIterator->First() ;
			while( !$aIterator->IsDone() )
			{
				$sViewVaribleName = $this->GetJSVariableName() ;
			
				$aChildView = $aIterator->Current() ;
				ASSERT::ASSERT_INSTANCE($aChildView,'JCAT\IJSObject')  ;
				$sChildViewVarName = $aChildView->GetJSVariableName() ;
				
				print "if( typeof({$sChildViewVarName})=='object' ){\r\n" ;
				print "{$sViewVaribleName}.AddView({$sChildViewVarName});\r\n" ;
				print "}\r\n" ;
				
				$aIterator->Next() ;
			}
		}
	}
	

	/**
	 * create a iterator for html resources
	 *
	 * @access	public
	 * @param	$bRecursion=false		bool		if this object has child object and $bRecursion=true, iterator will iterate all child's
	 * @return	IIterator
	 */
	public function CreateHTMLResourceIterator($bRecursion=false)
	{
		if($bRecursion)
		{
			// my resource
			$arrHtmlResrcsIterators[] = $this->CreateHTMLResourceIterator(false) ;
			
			// children view's and UICtrl's
			foreach ( array($this->CreateViewIterator(),$this->CreateUICtrlIterator()) as $aContainnerIterator)
			{
				for ($aContainnerIterator->First();!$aContainnerIterator->IsDone();$aContainnerIterator->Next())
				{
					// a child view or a UICtrl
					$aHtmlResrcContainner = $aContainnerIterator->Current() ;
					
					if( GlobalFunc::HasImplementedTo($aHtmlResrcContainner,'IHTMLResourceContainer') )
					{
						$arrHtmlResrcsIterators[] = $aHtmlResrcContainner->CreateHTMLResourceIterator(true) ;
					}
				}
			}
			
			// link all of these iterators(mine,child view's, and UICtrl's) as a single iterator
			return new MultiIterator($arrHtmlResrcsIterators) ;
		}
		
		else 
		{
			return new ArrayIterator($this->arrHTMLResources) ;
		}
	}
	
	
	/**
	 * add a html resource, only call this method inner
	 *
	 * @access	protected
	 * @param	$bRecursion=false		bool
	 * @return	void
	 */
	protected function AddHTMLResource(IHTMLResource $aHtmlResource)
	{
		if( !in_array($aHtmlResource,$this->arrHTMLResources,true) )
		{
			$this->arrHTMLResources[] = $aHtmlResource ;
		}
	}
	
	// 属性 ///////////////////////////////////////////////////////////////////////////////


	static private $aShareGlobalUI ;
		
	private $sTemplate ;
	
	
	/**
	 * 
	 * 
	 * @access	private
	 * @var		bool
	 */
	private $bEnableView = true ;
	
	private $arrHTMLResources = array() ;
	
	static private $sViewGlabalIdx = 0 ;
}
?>